home *** CD-ROM | disk | FTP | other *** search
/ JCSM Shareware Collection 1993 November / JCSM Shareware Collection - 1993-11.iso / cl720 / sst115j.lzh / SSTWIN.C < prev    next >
C/C++ Source or Header  |  1992-07-18  |  23KB  |  752 lines

  1. /* ------------------------------------------------------------------------ */
  2. /*                                 sstwin.c                                 */
  3. /*                         high-level window routines                       */
  4. /*                                                                          */
  5. /*      CopyRight (C) 1991,1992  Steven Lutrov.   All rights reserved.      */
  6. /*                                                                          */
  7. /* ------------------------------------------------------------------------ */
  8. #include <stdio.h>
  9. #include <ctype.h>
  10. #include <stdarg.h>
  11. #include <dos.h>
  12. #include <alloc.h>
  13. #include <stdlib.h>
  14. #include <string.h>
  15.  
  16. #include "sstvid.h"
  17. #include "sstwin.h"
  18. #include "sstedt.h"
  19. #include "sstkey.h"
  20.  
  21. /* ------------------------------------------------------------------------ */
  22. /*                            local prototypes                              */
  23. /* ------------------------------------------------------------------------ */
  24. static void redraw       (WINDOW *wnd);
  25. static void wframe       (WINDOW *wnd);
  26. static void dtitle       (WINDOW *wnd);
  27. static void dfooter      (WINDOW *wnd);
  28. static int  *waddr       (WINDOW *wnd, int x, int y);
  29. static void vswap        (WINDOW *wnd);
  30.  
  31. static void listadd      (WINDOW *wnd);
  32. static void listbegin    (WINDOW *wnd);
  33. static void listdelete   (WINDOW *wnd);
  34. static void listinsert   (WINDOW *w1, WINDOW *w2);
  35. static int  wpeek        (WINDOW *wnd, int x, int y);
  36. static int  wndverify    (WINDOW **wndc);
  37. void wndrepos    (WINDOW *wnd, int x, int y, int z);
  38.  
  39.  
  40.  
  41. /* ------------------------------------------------------------------------ */
  42. /*                 window structure linked list head & tail                 */
  43. /* ------------------------------------------------------------------------ */
  44. WINDOW *listhead = NULL;     /* head address */
  45. WINDOW *listtail = NULL;     /* tail address */
  46.  
  47. /* ------------------------------------------------------------------------ */
  48. /*                   array of border character sets                         */
  49. /* ------------------------------------------------------------------------ */
  50. struct {
  51.     unsigned char topleft, topright, botright, botleft, vert, hor;
  52. } wcs[] = {
  53.     { 32, 32, 32, 32, 32, 32},    /* blank line */
  54.     {218,191,217,192,179,196},    /* single line */
  55.     {201,187,188,200,186,205},    /* double line */
  56.     {214,183,189,211,186,196},    /* single top, double side */
  57.     {213,184,190,212,179,205},    /* double top, single side */
  58.     {194,194,217,192,179,196},    /* single - pop-down menu */
  59.     {203,203,188,200,186,205},    /* double - pop-down menu */
  60.     {210,210,189,211,186,196},    /* single top pop-down menu */
  61.     {209,209,190,212,179,205},    /* double top pop-down menu */
  62.     { 32, 32, 32, 32, 32, 32},    /* blank line */
  63. };
  64. /* ------------------------------------------------------------------------ */
  65. /*                          establish a new window                          */
  66. /* ------------------------------------------------------------------------ */
  67. WINDOW *Westablish(int x, int y, int h, int w)
  68. {
  69.     WINDOW *wnd;
  70.  
  71.     if ((wnd = (WINDOW *) malloc(sizeof (WINDOW))) == NULL)
  72.         return NULL;
  73.     WTITLE = "";
  74.     WFOOT  = "";
  75.     TJUST = FJUST = JUST_C;
  76.     HEIGHT = min(h, SCREENHEIGHT);
  77.     WIDTH = min(w, SCREENWIDTH);
  78.     COL = max(0, min(x, SCREENWIDTH-WIDTH));
  79.     ROW = max(0, min(y, SCREENHEIGHT-HEIGHT));
  80.     WCURS = 0;
  81.     SCROLL = 0;
  82.     SELECT = 1;
  83.     BTYPE = 1;
  84.     VISIBLE = HIDDEN = 0;
  85.     PREV = NEXT = NULL;
  86.     FHEAD = FTAIL = NULL;
  87.     WBORDER=WFACE=PWIN_FACE=WTITLEC=WFIELD = CLR(BLACK, WHITE, BRIGHT);
  88.     WACCENT = CLR(WHITE, BLACK, DIM);
  89.     if ((SAV = (char *)malloc(WIDTH * HEIGHT * 2)) == (char *) 0)
  90.         return NULL;
  91.     listadd(wnd);
  92.     Wclear(wnd);
  93.     wframe(wnd);
  94.     return wnd;
  95. }
  96.  
  97. /* ------------------------------------------------------------------------ */
  98. /*                         set the window's border                          */
  99. /* ------------------------------------------------------------------------ */
  100. void Wsetborder(WINDOW *wnd, int btype)
  101. {
  102.    if (wndverify(&wnd)) {
  103.     BTYPE = btype;
  104.     wframe(wnd);
  105.     redraw(wnd);
  106.   }
  107. }
  108.  
  109. /* ------------------------------------------------------------------------ */
  110. /*                               set colours                                */
  111. /* ------------------------------------------------------------------------ */
  112. void Wsetcolour(WINDOW *wnd,int area,int bg,int fg,int inten)
  113. {
  114.     if (ISMONO() )    {
  115.         if (bg != WHITE && bg != BLACK)
  116.             return;
  117.         if (fg != WHITE && fg != BLACK)
  118.             return;
  119.     }
  120.     if (wndverify(&wnd))    {
  121.         if (area == WIN_ALL)
  122.             while (area)
  123.         WCOLOUR [--area] = CLR(bg, fg, inten);
  124.         else
  125.         WCOLOUR [area] = CLR(bg, fg, inten);
  126.         redraw(wnd);
  127.     }
  128. }
  129.  
  130. /* ------------------------------------------------------------------------ */
  131. /*                      set the intensity of a window                       */
  132. /* ------------------------------------------------------------------------ */
  133. void Wsetintensity(WINDOW *wnd, int inten)
  134. {
  135.     int area = WIN_ALL;
  136.  
  137.     if (wndverify(&wnd))    {
  138.         while (area)    {
  139.             WCOLOUR [--area] &= ~BRIGHT;
  140.         WCOLOUR [area] |= inten;
  141.         }
  142.         redraw(wnd);
  143.     }
  144. }
  145.  
  146. /* ------------------------------------------------------------------------ */
  147. /*                               set title                                  */
  148. /* ------------------------------------------------------------------------ */
  149. void Wsettitle(WINDOW *wnd, char *title, int just)
  150. {
  151.     if (wndverify(&wnd))    {
  152.         WTITLE = title;
  153.         TJUST = just;
  154.         redraw(wnd);
  155.     }
  156. }
  157. /* ------------------------------------------------------------------------ */
  158. /*                           set window footer                              */
  159. /* ------------------------------------------------------------------------ */
  160. void Wsetfooter(WINDOW *wnd, char *s, int j)
  161. {
  162.     if (wndverify(&wnd))    {
  163.         WFOOT = s;
  164.         FJUST = j;
  165.         redraw(wnd);
  166.     }
  167. }
  168.  
  169. /* ------------------------------------------------------------------------ */
  170. /*                redraw a window when an attribute changes                 */
  171. /* ------------------------------------------------------------------------ */
  172. static void redraw(WINDOW *wnd)
  173. {
  174.     int x, y, chat, atr;
  175.  
  176.     for (y = BORDER_OFFSET; y < HEIGHT-BORDER_OFFSET; y++)
  177.     for (x = BORDER_OFFSET; x < WIDTH-BORDER_OFFSET; x++)    {
  178.         chat = wpeek(wnd, x, y);
  179.         atr = (((chat>>8)&255) == PWIN_FACE ? WFACE : WACCENT);
  180.           displ(wnd, x, y, chat&255, atr);
  181.         }
  182.     if (BTYPE != BRD_NOBORDER)
  183.        wframe(wnd);
  184.     PWIN_FACE = WFACE;
  185. }
  186.  
  187. /* ------------------------------------------------------------------------ */
  188. /*                      display an established window                       */
  189. /* ------------------------------------------------------------------------ */
  190. void Wshow(WINDOW *wnd)
  191. {
  192.   if (wndverify(&wnd) && !VISIBLE)    {
  193.     VISIBLE = 1;
  194.     vswap(wnd);
  195.   }
  196. }
  197.  
  198. /* ------------------------------------------------------------------------ */
  199. /*                          close all windows                               */
  200. /* ------------------------------------------------------------------------ */
  201. void Wdeleteall()
  202. {
  203.     WINDOW *sav, *wnd = listtail;
  204.  
  205.     while (wnd)    {
  206.         sav = PREV;
  207.         Wdelete(wnd);
  208.         wnd = sav;
  209.     }
  210. }
  211.  
  212. /* ------------------------------------------------------------------------ */
  213. /*                           remove a window                                */
  214. /* ------------------------------------------------------------------------ */
  215. void Wdelete(WINDOW *wnd)
  216. {
  217.     if (wndverify(&wnd))        {
  218.         Whide(wnd);
  219.         free(SAV);
  220.         listdelete(wnd);    /* remove window from list */
  221.         free(wnd);
  222.     }
  223. }
  224. /* ------------------------------------------------------------------------ */
  225. /*                             hide a window                                */
  226. /* ------------------------------------------------------------------------ */
  227. void Whide(WINDOW *wnd)
  228. {
  229.     if (wndverify(&wnd) && VISIBLE)    {
  230.         vswap(wnd);
  231.         HIDDEN = 1;
  232.         VISIBLE = 0;
  233.     }
  234. }
  235.  
  236. /* ------------------------------------------------------------------------ */
  237. /*                 reposition the window in its 3-axis plane                */
  238. /* ------------------------------------------------------------------------ */
  239. void wndrepos(WINDOW *wnd, int x, int y, int z)
  240. {
  241.     WINDOW *twnd;
  242.     int x1, y1, chat;
  243.  
  244.     if (!wndverify(&wnd))
  245.         return;
  246.     twnd = Westablish(x+COL, y+ROW, HEIGHT, WIDTH);
  247.     twnd->_title = WTITLE;
  248.     twnd->_tjust = TJUST;
  249.     twnd->_footer = WFOOT;
  250.     twnd->_fjust = FJUST;
  251.     twnd->btype = BTYPE;
  252.     twnd->wcolour[WIN_BORDER] = WBORDER;
  253.     twnd->wcolour[WIN_TITLE] = WTITLEC;
  254.     twnd->wcolour[WIN_ACCENT] = WACCENT;
  255.     twnd->wcolour[WIN_FACE] = WFACE;
  256.     twnd->_wsp = SCROLL;
  257.     twnd->_cr = WCURS;
  258.     if (z != 1)    {
  259.         listdelete(twnd);
  260.         if (z == 0)
  261.             listinsert(twnd, wnd);
  262.         else
  263.             listbegin(twnd);
  264.     }
  265.     for (y1 = 0; y1 < twnd->_wh; y1++)
  266.         for (x1 = 0; x1 < twnd->_ww; x1++)    {
  267.             chat = wpeek(wnd, x1, y1);
  268.             displ(twnd, x1, y1, chat&255, (chat>>8)&255);
  269.         }
  270.     twnd->_wv = 1;
  271.     vswap(twnd);
  272.     Whide(wnd);
  273.     free(SAV);
  274.     listdelete(wnd);
  275.     *wnd = *twnd;
  276.     listinsert(wnd, twnd);
  277.     listdelete(twnd);
  278.     free(twnd);
  279. }
  280.  
  281. /* ------------------------------------------------------------------------ */
  282. /*                           clear the window area                          */
  283. /* ------------------------------------------------------------------------ */
  284. void Wclear(WINDOW *wnd)
  285. {
  286.    register int x1, y1;
  287.  
  288.    if (wndverify(&wnd))
  289.     for (y1 = BORDER_OFFSET; y1 < HEIGHT-BORDER_OFFSET; y1++)
  290.         for (x1 = BORDER_OFFSET; x1 < WIDTH-BORDER_OFFSET; x1++)
  291.             displ(wnd,x1, y1, ' ', WFACE);
  292. }
  293.  
  294. /* ------------------------------------------------------------------------ */
  295. /*                           window-oriented printf                         */
  296. /* ------------------------------------------------------------------------ */
  297. void Wprintf(WINDOW *wnd, char *ln, ...)
  298. {
  299.    char dlin [100], *dl = dlin;
  300.  
  301.    if (wndverify(&wnd))   {
  302.      va_list ap;
  303.      va_start(ap, ln);
  304.      vsprintf(dlin, ln, ap);
  305.      va_end(ap);
  306.      while (*dl)
  307.         Wputch(wnd, *dl++);
  308.       }
  309. }
  310.  
  311. /* ------------------------------------------------------------------------ */
  312. /*                     write a character to the window                      */
  313. /* ------------------------------------------------------------------------ */
  314. void Wputch(WINDOW *wnd, int c)
  315. {
  316.     if (!wndverify(&wnd))
  317.         return;
  318.     switch (c)    {
  319.         case '\n':
  320.             if (SCROLL == HEIGHT-(2*BORDER_OFFSET)-1)
  321.                 scroll(wnd, UP);
  322.             else
  323.                 SCROLL++;
  324.             WCURS = 0;
  325.             break;
  326.         case '\t':
  327.              do {
  328.            displ(wnd,(WCURS++)+BORDER_OFFSET,SCROLL+BORDER_OFFSET,' ',WFACE);
  329.             }while ((WCURS%TABS) && (WCURS+BORDER_OFFSET) < WIDTH-(BORDER_OFFSET*2));
  330.             break;
  331.         default:
  332.             if ((WCURS+BORDER_OFFSET) < WIDTH-BORDER_OFFSET)    {
  333.                 displ(wnd, WCURS+BORDER_OFFSET, SCROLL+BORDER_OFFSET, c, WFACE);
  334.                 WCURS++;
  335.             }
  336.             break;
  337.     }
  338. }
  339.  
  340. /* ------------------------------------------------------------------------ */
  341. /*                write a character and attribute to the window             */
  342. /* ------------------------------------------------------------------------ */
  343. void Wputchat(WINDOW *wnd, int c, int bg, int fg, int i)
  344. {
  345.     if (!wndverify(&wnd))
  346.         return;
  347.     switch (c)    {
  348.         case '\n':
  349.             if (SCROLL == HEIGHT-(2*BORDER_OFFSET)-1)
  350.                 scroll(wnd, UP);
  351.             else
  352.                 SCROLL++;
  353.             WCURS = 0;
  354.             break;
  355.         case '\t':
  356.             do {
  357.                displ(wnd,(WCURS++)+BORDER_OFFSET,SCROLL+BORDER_OFFSET,' ',WFACE);
  358.             }while ((WCURS%TABS) && (WCURS+BORDER_OFFSET) < WIDTH-(BORDER_OFFSET*2));
  359.             break;
  360.         default:
  361.             if ((WCURS+BORDER_OFFSET) < WIDTH-BORDER_OFFSET)    {
  362.                 displ(wnd, WCURS+BORDER_OFFSET, SCROLL+BORDER_OFFSET, c,CLR(bg,fg,i));
  363.                 WCURS++;
  364.             }
  365.             break;
  366.     }
  367. }
  368.  
  369. /* ------------------------------------------------------------------------ */
  370. /*                             set window cursor                            */
  371. /* ------------------------------------------------------------------------ */
  372. void Wcursor(WINDOW *wnd, int x, int y)
  373. {
  374.     if (wndverify(&wnd) &&
  375.     x < WIDTH-BORDER_OFFSET && y < HEIGHT-BORDER_OFFSET)   {
  376.         WCURS = x;
  377.         SCROLL = y;
  378.     vsetcur(COL+x+BORDER_OFFSET, ROW+y+BORDER_OFFSET);
  379.      }
  380. }
  381.  
  382. /* ------------------------------------------------------------------------ */
  383. /*               allow the user to make a window selection                  */
  384. /* ------------------------------------------------------------------------ */
  385. int Wgetsel(WINDOW *wnd, int s, char *keys)
  386. {
  387.    int c = 0, ky;
  388.    if (!wndverify(&wnd))
  389.         return 0;
  390.    SELECT = s;
  391.    while (c != ESC && c != '\r' && c != LEFT && c != RIGHT)    {
  392.     accent(wnd);
  393.     c = kgetch();
  394.     deaccent(wnd);
  395.     switch (c)   {
  396.           case UP:    if (SELECT >  1)
  397.                 SELECT--;
  398.                 else
  399.                 SELECT = SCROLL+1;
  400.             break;
  401.           case DOWN: if (SELECT < SCROLL+1)
  402.                 SELECT++;
  403.                else
  404.                 SELECT = 1;
  405.                break;
  406.           case '\r' :
  407.           case ESC  :
  408.           case RIGHT:
  409.           case LEFT :    break;
  410.  
  411.           default   :   if (keys)    {
  412.                   ky = 0;
  413.                   while (*(keys + ky))    {
  414.                 if (*(keys+ky)==toupper(c) ||
  415.                     *(keys+ky)==tolower(c))
  416.                         return ky + 1;
  417.                         ky++;
  418.                 }
  419.                   }
  420.                  break;
  421.         }
  422.     }
  423.     return     c == '\r' ? SELECT : c == ESC ? 0 : c;
  424. }
  425.  
  426. union REGS rg;
  427.  
  428. /* ------------------------------------------------------------------------ */
  429. /*                   scroll a window's contents up or down                  */
  430. /* ------------------------------------------------------------------------ */
  431. void scroll(WINDOW *wnd, int dir)
  432. {
  433.     int row = HEIGHT-1, col, chat;
  434.  
  435.     if (!wndverify(&wnd))
  436.         return;
  437.  
  438.     if (NEXT == NULL && HEIGHT > 3 && VISIBLE)    {
  439.         rg.h.ah = dir == UP ? 6 : 7;
  440.         rg.h.al = 1;
  441.         rg.h.bh = WFACE;
  442.         rg.h.cl = COL + BORDER_OFFSET;
  443.         rg.h.ch = ROW + BORDER_OFFSET;
  444.         rg.h.dl = COL + WIDTH - (BORDER_OFFSET+1);
  445.         rg.h.dh = ROW + HEIGHT - (BORDER_OFFSET+1);
  446.         int86(VIDEO, &rg, &rg);
  447.         return;
  448.     }
  449.     if (dir == UP)    {
  450.         for (row = 1+BORDER_OFFSET; row < HEIGHT-BORDER_OFFSET; row++)
  451.            for (col = BORDER_OFFSET; col < WIDTH-BORDER_OFFSET; col++)    {
  452.              chat = wpeek(wnd, col, row);
  453.              displ(wnd,col,row-1,chat&255,(chat>>8)&255);
  454.             }
  455.         for (col = BORDER_OFFSET; col < WIDTH-BORDER_OFFSET; col++)
  456.             displ(wnd, col, row-1, ' ', WFACE);
  457.     }
  458.     else    {
  459.         for (row = HEIGHT-(BORDER_OFFSET+1); row > BORDER_OFFSET; --row)
  460.              for (col = BORDER_OFFSET; col < WIDTH-BORDER_OFFSET; col++)    {
  461.              chat = wpeek(wnd, col, row);
  462.              displ(wnd,col,row+1,chat&255,(chat>>8)&255);
  463.             }
  464.         for (col = BORDER_OFFSET; col < WIDTH-BORDER_OFFSET; col++)
  465.             displ(wnd, col, row+1, ' ', WFACE);
  466.     }
  467. }
  468.  
  469. /* ------------------------------------------------------------------------ */
  470. /*                         draw the window frame                            */
  471. /* ------------------------------------------------------------------------ */
  472. static void wframe(WINDOW *wnd)
  473. {
  474.     register int x, y;
  475.  
  476.     if (!wndverify(&wnd))
  477.         return;
  478.     /* --------- window title -------------- */
  479.     displ(wnd,0, 0, NW, WBORDER);
  480.     dtitle(wnd);
  481.     displ(wnd,WIDTH-1, 0, NE, WBORDER);
  482.     /* ---------- do window sides -------------- */
  483.     for (y = 1; y < HEIGHT-1; y++)    {
  484.         displ(wnd,0, y, SIDE, WBORDER);
  485.         displ(wnd,WIDTH-1, y, SIDE, WBORDER);
  486.     }
  487.     /* --------------- do bottom of frame ---------------- */
  488.     displ(wnd,0, y, SW, WBORDER);
  489.     for (x = 1; x < WIDTH-1; x++)
  490.         displ(wnd,x, y, LINE, WBORDER);
  491.     displ(wnd,x, y, SE, WBORDER);
  492.     dfooter(wnd);
  493. }
  494.  
  495. /* ------------------------------------------------------------------------ */
  496. /*                         display the window title                         */
  497. /* ------------------------------------------------------------------------ */
  498. static void dtitle(WINDOW *wnd)
  499.  
  500. {
  501.    int x = 1, i, ln;
  502.    char *s = WTITLE;
  503.  
  504.    if (!wndverify(&wnd))
  505.     return;
  506.  
  507.    switch (TJUST) {
  508.     case JUST_L : {
  509.               x =1;
  510.              while (*s)
  511.                  displ(wnd, x++, 0, *s++, WTITLEC);
  512.              while (x < WIDTH-1)
  513.                  displ(wnd, x++, 0, LINE, WBORDER);
  514.               }
  515.              break;
  516.     case JUST_R : {   i = 1;
  517.              while (i < WIDTH-1)
  518.                  displ(wnd, i++, 0, LINE, WBORDER);
  519.              x = ( (WIDTH-1) - strlen(s));
  520.              while (*s)
  521.                  displ(wnd, x++, 0, *s++, WTITLEC);
  522.               }
  523.              break;
  524.     default    : if (s) {
  525.             ln = strlen(s);
  526.             if (ln > WIDTH-2) /* if max screen length -2 */
  527.             i = 0;
  528.              else
  529.               i = ((WIDTH-2-ln) / 2);  /* centre */
  530.               if (i > 0)
  531.                 while (i--)
  532.                     displ(wnd, x++, 0, LINE, WBORDER);
  533.               while (*s && x < WIDTH-1)
  534.                  displ(wnd, x++, 0, *s++, WTITLEC);
  535.                }
  536.              while (x < WIDTH-1)
  537.              displ(wnd, x++, 0, LINE, WBORDER);
  538.    } /* switch */
  539.  
  540.  
  541. }
  542.  
  543. /* ------------------------------------------------------------------------ */
  544. /*                         display the window title                         */
  545. /* ------------------------------------------------------------------------ */
  546. static void dfooter(WINDOW *wnd)
  547.  
  548. {
  549.    int x = 1, i, ln;
  550.    char *s = WFOOT;
  551.  
  552.    if (!wndverify(&wnd))
  553.     return;
  554.    if (! s)
  555.       return;
  556.  
  557.    switch (FJUST) {
  558.     case JUST_L : {
  559.               x =1;
  560.              while (*s)
  561.                  displ(wnd, x++, HEIGHT-1, *s++, WFOOTC);
  562.              while (x < WIDTH-1)
  563.                  displ(wnd, x++, HEIGHT-1, LINE, WBORDER);
  564.               }
  565.              break;
  566.     case JUST_R : {   i = 1;
  567.              while (i < WIDTH-1)
  568.                  displ(wnd, i++, HEIGHT-1, LINE, WBORDER);
  569.              x = ( (WIDTH-1) - strlen(s));
  570.              while (*s)
  571.                  displ(wnd, x++, HEIGHT-1, *s++, WFOOTC);
  572.               }
  573.              break;
  574.     default    : ln = strlen(s);
  575.              if (ln > WIDTH-2) /* if max screen length -2 */
  576.              i = 0;
  577.              else
  578.               i = ((WIDTH-2-ln) / 2);  /* centre */
  579.               if (i > 0)
  580.                 while (i--)
  581.                     displ(wnd, x++, HEIGHT-1, LINE, WBORDER);
  582.               while (*s && x < WIDTH-1)
  583.                  displ(wnd, x++, HEIGHT-1, *s++, WFOOTC);
  584.              while (x < WIDTH-1)
  585.              displ(wnd, x++, HEIGHT-1, LINE, WBORDER);
  586.    } /* switch */
  587. }
  588.  
  589. /* ------------------------------------------------------------------------ */
  590. /*              compute address of a window's display character             */
  591. /* ------------------------------------------------------------------------ */
  592. static int *waddr(WINDOW *wnd, int x, int y)
  593. {
  594.    WINDOW *nxt = NEXT;
  595.    int *vp;
  596.  
  597.    if (!VISIBLE)
  598.     return (int *) (SAV+y*(WIDTH*2)+x*2);
  599.    x += COL;
  600.    y += ROW;
  601.    while (nxt)    {
  602.     if (nxt->_wv)
  603.       if (x >= nxt->_wx && x <= nxt->_wx + nxt->_ww-1)
  604.           if (y >= nxt->_wy && y <= nxt->_wy + nxt->_wh-1)    {
  605.               x -= nxt->_wx;
  606.               y -= nxt->_wy;
  607.               vp = (int *)    ((nxt->_ws) +y*(nxt->_ww*2)+x*2);
  608.               return vp;
  609.               }
  610.          nxt = nxt->_nx;
  611.     }
  612.  return NULL;
  613. }
  614.  
  615. /* ------------------------------------------------------------------------ */
  616. /*                    display a character to a window                       */
  617. /* ------------------------------------------------------------------------ */
  618. void displ(WINDOW *wnd, int x, int y, int ch, int at)
  619. {
  620.      int *vp;
  621.      int vch = (ch&255)|(at<<8);
  622.  
  623.      if ((vp = waddr(wnd, x, y)) != NULL)
  624.     *vp = vch;
  625.      else
  626.     vputch(x+COL,y+ROW,at,ch);
  627. }
  628.  
  629. /* ------------------------------------------------------------------------ */
  630. /*                    get a displayed character from a window               */
  631. /* ------------------------------------------------------------------------ */
  632. static int wpeek(WINDOW *wnd, int x, int y)
  633. {
  634.      int *vp;
  635.  
  636.      if ((vp = waddr(wnd, x, y)) != NULL)
  637.         return *vp;
  638.      return (vget(x+COL,y+ROW));
  639. }
  640.  
  641. /* ------------------------------------------------------------------------ */
  642. /*                  swap the video image with the save buffer               */
  643. /* ------------------------------------------------------------------------ */
  644. static void vswap(WINDOW *wnd)
  645. {
  646.     int x, y, chat;
  647.     int *bf = (int *) SAV;
  648.  
  649.     for (y = 0; y < HEIGHT; y++)
  650.         for (x = 0; x < WIDTH; x++)    {
  651.             chat = *bf;
  652.             *bf++ = wpeek(wnd, x, y);
  653.             displ(wnd, x, y, chat&255, (chat>>8)&255);
  654.         }
  655. }
  656.  
  657. /* ------------------------------------------------------------------------ */
  658. /*                 (de)accent the line where SELECT points                  */
  659. /* ------------------------------------------------------------------------ */
  660. void acline(WINDOW *wnd, int set)
  661. {
  662.     int x, ch;
  663.  
  664.     if (!wndverify(&wnd))
  665.         return;
  666.     for (x = 1; x < WIDTH - 1; x++)    {
  667.         ch = wpeek(wnd, x, SELECT) & 255;
  668.         displ(wnd, x, SELECT, ch, set);
  669.     }
  670. }
  671.  
  672. /* ------------------------------------------------------------------------ */
  673. /*                   add a window to the end of the list                    */
  674. /* ------------------------------------------------------------------------ */
  675. static void listadd(WINDOW *wnd)
  676. {
  677.     if (listtail)    {
  678.         PREV = listtail;
  679.         listtail->_nx = wnd;
  680.     }
  681.     listtail = wnd;
  682.     if (!listhead)
  683.         listhead = wnd;
  684. }
  685.  
  686. /* ------------------------------------------------------------------------ */
  687. /*                add a window to the beginning of the list                 */
  688. /* ------------------------------------------------------------------------ */
  689. static void listbegin(WINDOW *wnd)
  690. {
  691.     if (listhead)    {
  692.         NEXT = listhead;
  693.         listhead->_pv = wnd;
  694.     }
  695.     listhead = wnd;
  696.     if (!listtail)
  697.         listtail = wnd;
  698. }
  699.  
  700. /* ------------------------------------------------------------------------ */
  701. /*                     remove a window from the list                        */
  702. /* ------------------------------------------------------------------------ */
  703. static void listdelete(WINDOW *wnd)
  704. {
  705.     if (NEXT)
  706.         NEXT->_pv = PREV;
  707.     if (PREV)
  708.         PREV->_nx = NEXT;
  709.     if (listhead == wnd)
  710.         listhead = NEXT;
  711.     if (listtail == wnd)
  712.         listtail = PREV;
  713.     NEXT = PREV = NULL;
  714. }
  715.  
  716. /* ------------------------------------------------------------------------ */
  717. /*                            insert w1 after w2                             */
  718. /* ------------------------------------------------------------------------ */
  719. static void listinsert(WINDOW *w1, WINDOW *w2)
  720. {
  721.     w1->_pv = w2;
  722.     w1->_nx = w2->_nx;
  723.     w2->_nx = w1;
  724.     if (w1->_nx == NULL)
  725.         listtail = w1;
  726.     else
  727.         w1->_nx->_pv = w1;
  728. }
  729.  
  730. /* ------------------------------------------------------------------------ */
  731. /*                 verify the presence of a window in the list              */
  732. /* ------------------------------------------------------------------------ */
  733. static int wndverify(WINDOW **wndc)
  734.  
  735. {
  736.      WINDOW *wnd;
  737.  
  738.      if (*wndc == NULL)
  739.         *wndc = listtail;
  740.      else    {
  741.     wnd = listhead;
  742.     while (wnd != NULL)    {
  743.         if (*wndc == wnd)
  744.             break;
  745.         wnd = NEXT;
  746.     }
  747.      }
  748.     return *wndc != NULL;
  749. }
  750.  
  751.  
  752.